#include<iostream>
#include<string>
#include<fstream>
#include<thread>
#include<mutex>
#include<pthread.h>
using namespace std;

#define LOGAPP Log::getInstance()

enum class log_level//等级
{
    debug,
    info,
    warn,
    error
};

class Log
{
    public:
        static Log* getInstance();
        ~Log() = delete;

        void writeLog(const string& logs,const string& log_name,int& log_time,log_level& lv);

        void setLog_name(string log_name){this->log_name = log_name;}
        string getLog_name(){return log_name;}

        void setLogs(string logs){this->logs = logs;}
        string getLogs(){return logs;}

        void setTime(int log_time){this->log_time = log_time;}
        int getTimes(){return log_time;}

        void setLog_level(log_level lv){this->lv = lv;}
        log_level getLog_level(){return lv;}

        

    private:
        Log() :  log_name("Logs.txt"), logs("no logs"), log_time(0), lv(log_level::debug){}
    private:
        string log_name;
        string logs;
        int log_time;
        log_level lv;
        static Log* m_log;
        static mutex m_mutex;
};
Log* Log::m_log = nullptr;
mutex Log::m_mutex;

Log* Log::getInstance()
{
    if(m_log == nullptr) {          
        lock_guard<mutex> lock(m_mutex);
        if(m_log == nullptr) {
            m_log = new Log();
        }
    }
    return m_log;
}

void Log::writeLog(const string& logs,const string& log_name,int& log_time,log_level& lv)
{
    string level;
    if (lv == log_level::debug)
        level = "debug ";
    else if (lv == log_level::info)
        level = "info ";
    else if (lv == log_level::warn)
        level = "warn ";
    else if (lv == log_level::error)
        level = "error ";
    else
    {
        return;
    }
    //上锁
    lock_guard<mutex> lock(m_mutex);
    ofstream ofs;
    
    LOGAPP->setLog_name(log_name);
    ofs.open(LOGAPP->getLog_name(),ios::app);

    
    LOGAPP->setLogs(logs);
    LOGAPP->setTime(log_time);

    ofs << level << LOGAPP->getLogs() << " " << LOGAPP->getTimes() << endl;

    ofs.close();
}

void write()
{
    
    string log_name = "log.txt";
    string logs = "this is log";
    log_level lv = log_level::debug;
    int log_time = 2023;
    LOGAPP->writeLog(logs,log_name,log_time,lv);
}

int main()
{
    thread t1(write);
    t1.join();
    thread t2(write);
    t2.join();
    return 0;
     
}